# include "Map.h"

# include "Renderer.h"

# include "Obstacle.h"
# include "ObjectConnect.h"
# include "Chest.h"
# include "ObjectPickUp.h"

Map::Map() : mySceneNode( 0), myTerrain( 0)
{

}

Map::~Map()
{
	if ( myPlane )
	{
		delete myPlane;
	}

	if ( myTerrain )
	{
		myRenderer->deleteEntity( myTerrain);
	}

	if ( mySceneNode )
	{
		myRenderer->deleteSceneNode( mySceneNode);
	}
}

Ogre::Plane* Map::getGround()
{
	return myPlane;
}

ObjectAction* Map::findAction( const Ogre::String& name)
{
	for ( unsigned int i = 0; i < myConnections.size(); i++ )
	{
		if ( myConnections[i]->getNodeName() == name )
		{
			return myConnections[i];
		}
	}

	for ( unsigned int i = 0; i < myChests.size(); i++ )
	{
		if ( myChests[i]->getNodeName() == name )
		{
			return myChests[i];
		}
	}

	for ( unsigned int i = 0; i < myObjects.size(); i++ )
	{
		if ( myObjects[i]->getNodeName() == name )
		{
			return myObjects[i];
		}
	}

	return NULL;
}

void Map::init( Renderer* renderer, const std::string& lua)
{
	myRenderer = renderer;
	myLua = lua;
	
	myPlane = new Ogre::Plane( Ogre::Vector3::UNIT_Y, 0);
}

void Map::loadMap( const Ogre::String& nameMap)
{
	Ogre::MeshManager::getSingleton().createPlane( "Map", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, *myPlane, 1500, 1500, 20, 20, true, 1, 5, 5, Ogre::Vector3::UNIT_Z);

	lua_State* stateTmp = lua_open();
	luaL_openlibs( stateTmp);
	luaL_dofile( stateTmp, myLua.c_str());
	lua_settop( stateTmp, 0);
	unsigned int indiceTmp = 1;

	lua_getglobal( stateTmp, nameMap.c_str());
	
	lua_pushnumber( stateTmp, indiceTmp++);
	lua_gettable( stateTmp, -2);
	myTerrain = myRenderer->createEntity( "Terrain", lua_tostring( stateTmp, -1));
	lua_pop( stateTmp, 1);
	myTerrain->setQueryFlags( GROUND_FLAG);

	mySceneNode = myRenderer->createSceneNode( "MapNode");
	mySceneNode->attachObject( myTerrain);
	
	lua_pushnumber( stateTmp, indiceTmp++);
	lua_gettable( stateTmp, -2);
	unsigned int numberTmp = lua_tonumber( stateTmp, -1);
	lua_pop( stateTmp, 1);

	for ( unsigned int i = 0; i < numberTmp; i++ )
	{
		myObstacles.push_back( new Obstacle());
		myObstacles[i]->init( myRenderer, "Resources/Lua/Building.lua");
		
		lua_pushnumber( stateTmp, indiceTmp++);
		lua_gettable( stateTmp, -2);
		myObstacles[i]->load( lua_tostring( stateTmp, -1));
		lua_pop( stateTmp, 1);

		float posXTmp, posYTmp, posZTmp;

		lua_pushnumber( stateTmp, indiceTmp++);
		lua_gettable( stateTmp, -2);
		posXTmp = lua_tonumber( stateTmp, -1);
		lua_pop( stateTmp, 1);

		lua_pushnumber( stateTmp, indiceTmp++);
		lua_gettable( stateTmp, -2);
		posYTmp = lua_tonumber( stateTmp, -1);
		lua_pop( stateTmp, 1);

		lua_pushnumber( stateTmp, indiceTmp++);
		lua_gettable( stateTmp, -2);
		posZTmp = lua_tonumber( stateTmp, -1);
		lua_pop( stateTmp, 1);

		myObstacles[i]->setPosition( Ogre::Vector3( posXTmp, posYTmp, posZTmp));
	}

	lua_pushnumber( stateTmp, indiceTmp++);
	lua_gettable( stateTmp, -2);
	numberTmp = lua_tonumber( stateTmp, -1);
	lua_pop( stateTmp, 1);

	for ( unsigned int i = 0; i < numberTmp; i++ )
	{
		myConnections.push_back( new ObjectConnect());
		myConnections[i]->init( myRenderer);
		
		lua_pushnumber( stateTmp, indiceTmp++);
		lua_gettable( stateTmp, -2);
		myConnections[i]->load( lua_tostring( stateTmp, -1));
		lua_pop( stateTmp, 1);
	}

	lua_pushnumber( stateTmp, indiceTmp++);
	lua_gettable( stateTmp, -2);
	numberTmp = lua_tonumber( stateTmp, -1);
	lua_pop( stateTmp, 1);

	for ( unsigned int i = 0; i < numberTmp; i++ )
	{
		myChests.push_back( new Chest());
		myChests[i]->init( myRenderer, this);

		lua_pushnumber( stateTmp, indiceTmp++);
		lua_gettable( stateTmp, -2);
		myChests[i]->load( lua_tostring( stateTmp, -1), i);
		lua_pop( stateTmp, 1);

		float posXTmp, posYTmp, posZTmp;

		lua_pushnumber( stateTmp, indiceTmp++);
		lua_gettable( stateTmp, -2);
		posXTmp = lua_tonumber( stateTmp, -1);
		lua_pop( stateTmp, 1);

		lua_pushnumber( stateTmp, indiceTmp++);
		lua_gettable( stateTmp, -2);
		posYTmp = lua_tonumber( stateTmp, -1);
		lua_pop( stateTmp, 1);

		lua_pushnumber( stateTmp, indiceTmp++);
		lua_gettable( stateTmp, -2);
		posZTmp = lua_tonumber( stateTmp, -1);
		lua_pop( stateTmp, 1);

		myChests[i]->setPosition( Ogre::Vector3( posXTmp, posYTmp, posZTmp));
	}

	lua_pop( stateTmp, 1);
	lua_close( stateTmp);
}

void Map::unloadMap()
{
	while ( !myObstacles.empty() )
	{
		delete myObstacles.back();
		myObstacles.pop_back();
	}

	while ( !myConnections.empty() )
	{
		delete myConnections.back();
		myConnections.pop_back();
	}

	while ( !myChests.empty() )
	{
		delete myChests.back();
		myChests.pop_back();
	}

	while ( !myObjects.empty() )
	{
		delete myObjects.back();
		myObjects.pop_back();
	}
	
	mySceneNode->detachObject( myTerrain);
	myRenderer->deleteEntity( myTerrain);
	myTerrain = NULL;
	myRenderer->deleteSceneNode( mySceneNode);
	mySceneNode = NULL;

	Ogre::MeshManager::getSingleton().remove( "Map");
}

void Map::addObjectPickUp( const std::string& name, const Ogre::Vector3& position)
{
	myObjects.push_back( new ObjectPickUp());

	myObjects.back()->init( myRenderer);
	myObjects.back()->load( name, myObjects.size()-1);
	myObjects.back()->setPosition( position + Ogre::Vector3( 50.0f, 0.0f, 0.0f));
}

void Map::deleteObjectPickUp( ObjectPickUp* object)
{
	for ( unsigned int i = 0; i < myObjects.size(); i++ )
	{
		if ( myObjects[i] == object )
		{
			delete myObjects[i];
			myObjects.erase( myObjects.begin() + i);
			return;
		}
	}
}